﻿namespace SharePointCSVImporter.Logger
{
    using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Text;
    using System.Xml.Linq;

    public class Logger
    {
        #region Fields

        private int errorCount;
        List<FieldErrorLog> errors;
        private int itemsDeleted;
        private int logCount = 0;
        private int successCount;

        #endregion Fields

        #region Properties

        public bool ContainsErrors
        {
            get
            {
                bool rvalue = false;
                if (errors != null && errors.Count > 0)
                {
                    rvalue = true;
                }
                return rvalue;
            }
            private set { }
        }

        public int ErrorCount
        {
            get { return errorCount; }
            set { errorCount = value; }
        }

        public List<FieldErrorLog> FieldErrors
        {
            get { return errors; }
            set { errors = value; }
        }

        public int ItemsDeleted
        {
            get { return itemsDeleted; }
            set { itemsDeleted = value; }
        }

        public int LogCount
        {
            get { return logCount; }
            set { logCount = value; }
        }

        public int SuccessCount
        {
            get { return successCount; }
            set { successCount = value; }
        }

        #endregion Properties

        #region Methods

        public static string GetErrorLogText(Logger logger)
        {
            string text = string.Empty;
            StringBuilder sb = new StringBuilder();
            sb.AppendLine("Date Attempted: " + DateTime.Now.ToString());
            sb.AppendLine(logger.ErrorCount + " Errors occurred out of " + logger.LogCount + " line items");
            sb.AppendLine(Environment.NewLine);
            sb.AppendLine("ApproxCSVLineNumber,errorMessage,data");
            if (logger != null)
            {
                if (logger.FieldErrors != null && logger.FieldErrors.Count > 0)
                {
                    foreach (var error in logger.FieldErrors)
                    {
                        sb.AppendLine(error.LineNumber + "," + error.ErrorMessage + "," + error.CsvLineData);
                    }
                }
            }
            text = sb.ToString();
            return text;
        }

        public void LogUpdateErrors(XElement updateResponse, XElement attemptedUpdatePackage)
        {
            var allCodex = from result in updateResponse.Elements()
                           from c in result.Descendants()
                           where c.Name.LocalName == "ErrorCode"
                           select c.Value;
            logCount = logCount + allCodex.Count();
            successCount = successCount + allCodex.Where(c => c == "0x00000000").Count();
            int thisErrorCount = allCodex.Where(c => c != "0x00000000").Count();
            errorCount = errorCount + thisErrorCount;
            if (thisErrorCount > 0)
            {
                var errorResults = (from result in updateResponse.Elements()
                                    from c in result.Descendants()
                                    where c.Name.LocalName == "ErrorCode" && c.Value != "0x00000000"
                                    select result).ToList();
                if (errorResults != null && errorResults.Count() > 0)
                {
                    ExtractAndLogBadUpdateAttempts(errorResults, attemptedUpdatePackage);
                }
            }
        }

        private void ExtractAndLogBadUpdateAttempts(List<XElement> errorResults, XElement attemptedUpdateBatch)
        {
            if (errorResults != null)
            {
                foreach (var result in errorResults)
                {
                    string IdAndOperation = result.Attribute("ID").Value.ToString();
                    if (!string.IsNullOrEmpty(IdAndOperation) && IdAndOperation.Contains(",") )
                    {
                        string strid = IdAndOperation.Split(',')[0];
                        int id;
                        if (int.TryParse(strid, out id))
                        {
                            string errorCode = result.Descendants().FirstOrDefault(c => c.Name.LocalName.Equals("ErrorCode")).Value;
                            string errorMessage = result.Descendants().FirstOrDefault(c => c.Name.LocalName.Equals("ErrorText")).Value;
                            XElement attemptedUpdate = (from method in attemptedUpdateBatch.Elements()
                                                        where method.Attribute("ID").Value.Equals(id.ToString())
                                                        select method).FirstOrDefault();
                            LogError(id, errorCode, errorMessage, attemptedUpdate);
                        }
                    }
                }
            }
        }

        private void LogError(int id, string errorCode, string errorMessage, XElement attemptedUpdate)
        {
            if (errors == null)
            {
                errors = new List<FieldErrorLog>();
            }
            FieldErrorLog logEntry = new FieldErrorLog();
            logEntry.LineNumber = id;
            logEntry.ErrorMessage = "Error: " + errorCode + ":  " + errorMessage;
            if (attemptedUpdate != null)
            {
                logEntry.CsvLineData = attemptedUpdate.ToString();
            }
            errors.Add(logEntry);
        }

        #endregion Methods
    }
}